package cn.cdeden.knowledge.service.impl;


import cn.cdeden.common.core.utils.MapstructUtils;
import cn.cdeden.common.core.utils.StringUtils;
import cn.cdeden.common.oss.enumd.OssBucketOneEnum;
import cn.cdeden.common.oss.enumd.OssModuleType;
import cn.cdeden.knowledge.enums.StorageTypeEnum;
import cn.cdeden.knowledge.utils.FileUtil;
import cn.cdeden.common.core.utils.page.TableDataInfo;
import cn.cdeden.common.mybatis.validator.QueryHelpMybatisPlus;
import cn.cdeden.common.satoken.utils.LoginHelper;
import cn.cdeden.knowledge.domain.TeamTemplateTree;
import cn.cdeden.knowledge.domain.dto.TeamTemplateTreeDto;
import cn.cdeden.knowledge.domain.dto.TeamTemplateTreeQueryParam;
import cn.cdeden.knowledge.mapper.TeamTemplateTreeMapper;
import cn.cdeden.knowledge.service.TeamTemplateTreeService;
import cn.cdeden.knowledge.utils.PageUtil;
import cn.cdeden.resource.api.RemoteFileService;
import cn.cdeden.resource.api.domain.RemoteFile;
import cn.cdeden.resource.api.domain.RemoteFileDto;
import cn.cdeden.system.api.model.LoginUser;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

/**
 * @author Chen
 * @date 2024-05-17
 */
@Service
@AllArgsConstructor
// @CacheConfig(cacheNames = TeamTemplateTreeService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class TeamTemplateTreeServiceImpl extends ServiceImpl<TeamTemplateTreeMapper, TeamTemplateTree> implements TeamTemplateTreeService {

    // private final RedisUtils redisUtils;
    private final TeamTemplateTreeMapper teamTemplateTreeMapper;
    @DubboReference
    private final RemoteFileService remoteFileService;
//    private final FileStorageUtils fileStorageUtils;

    @Override
    public TableDataInfo<TeamTemplateTreeDto> queryAll(TeamTemplateTreeQueryParam query, Pageable pageable) {
        IPage<TeamTemplateTree> queryPage = PageUtil.toMybatisPage(pageable);
        IPage<TeamTemplateTree> page = teamTemplateTreeMapper.selectPage(queryPage, QueryHelpMybatisPlus.getPredicate(query));
        return MapstructUtils.convertTableDataInfo(TableDataInfo.build(page), TeamTemplateTreeDto.class);
    }

    @Override
    public List<TeamTemplateTreeDto> queryAll(TeamTemplateTreeQueryParam query) {
        return MapstructUtils.convert(teamTemplateTreeMapper.selectList(QueryHelpMybatisPlus.getPredicate(query)), TeamTemplateTreeDto.class);
    }

    @Override
    public TeamTemplateTree getById(Long id) {
        return teamTemplateTreeMapper.selectById(id);
    }

    @Override
    // @Cacheable(key = "'id:' + #p0")
    public TeamTemplateTreeDto findById(Long id) {
        return MapstructUtils.convert(getById(id), TeamTemplateTreeDto.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insert(TeamTemplateTreeDto resources) {
        TeamTemplateTree entity = MapstructUtils.convert(resources, TeamTemplateTree.class);
        return this.save(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(TeamTemplateTreeDto resources) {
        TeamTemplateTree entity = MapstructUtils.convert(resources, TeamTemplateTree.class);
        boolean ret = this.updateById(entity);
        // delCaches(resources.id);
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(Set<Long> ids) {
        // delCaches(ids);
        return this.removeByIds(ids);
    }

    @Override
    public void uploadTemplate(MultipartFile image, MultipartFile file, String realName, Long teamId) throws Exception {
        LoginUser user = LoginHelper.getLoginUser();
        if (file == null) {
            throw new RuntimeException("错误请求参数file，不能为null");
        }
        if (StringUtils.isNullOrBlank(realName)) {
            realName = FileUtil.getFileNameNoEx(file.getOriginalFilename());
        }
        String filename = file.getOriginalFilename();
        String extensionName = FileUtil.getExtensionName(filename);
        String documentType = FileUtil.getDocumentType(extensionName);
        if (documentType == null) {
            throw new RuntimeException("上传文件格式有误");
        }
        //校验名称
        if (isExistRealName(realName, documentType, teamId))
            throw new RuntimeException("存在相同模板文件名称");
        RemoteFile remoteFile;
        RemoteFileDto build;
        if (image == null || image.isEmpty()) {
            build = RemoteFileDto.builder().name(file.getName())
                .file(file.getBytes())
                .bucketName(OssBucketOneEnum
                    .TEAM_BUCKET.getCode())
                .originalFilename(file.getOriginalFilename())
                .moduleType(OssModuleType.TeamTemplate).build();
        } else {
            build = RemoteFileDto.builder().name(file.getName())
                .file(file.getBytes())
                .bucketName(OssBucketOneEnum
                    .TEAM_BUCKET.getCode())
                .originalFilename(file.getOriginalFilename())
                .moduleType(OssModuleType.TeamTemplate).build();
        }
        build.setContentType("file");
        remoteFile = remoteFileService.upload(build);
        Long storageId = remoteFile.getOssId();
        TeamTemplateTree templateTree = new TeamTemplateTree();
        templateTree.setStorageId(storageId.toString())
            .setCreateId(user.getUserId().toString())
            .setType(documentType)
            .setStorageType(StorageTypeEnum.MINIO.getType())
            .setSuffix(extensionName)
            .setRealName(realName)
            .setTeamId(teamId);
        teamTemplateTreeMapper.insert(templateTree);
    }

    @Override
    public void updateTemplate(Long id, String realName) {
        if (id == null || StringUtils.isNullOrBlank(realName))
            throw new RuntimeException("参数不能为空");
        TeamTemplateTree teamTemplateTree = new TeamTemplateTree();
        teamTemplateTree.setId(id);
        teamTemplateTree.setRealName(realName);
        teamTemplateTreeMapper.updateById(teamTemplateTree);
    }

    @Override
    public void removeTeamTemplate(Long id) {
        TeamTemplateTreeDto byId = findById(id);
        if (byId != null) {
            removeTemplate(byId);
        } else {
            throw new RuntimeException("传递参数值错误");
        }
    }

    @Override
    public void uploadTemplateAdmin(Long teamId, List<MultipartFile> files) {
        LoginUser user = LoginHelper.getLoginUser();
        if (files == null || files.size() == 0) {
            throw new RuntimeException("上传文件为空");
        }
        for (MultipartFile file : files) {
            TeamTemplateTree teamTemplateTree = new TeamTemplateTree();
            String filename = file.getOriginalFilename();
            String extensionName = FileUtil.getExtensionName(filename);
            String realName = FileUtil.getFileNameNoEx(filename);
            String documentType = FileUtil.getDocumentType(extensionName);
            if (documentType == null) {
                continue;
            }
            //校验名称
            if (isExistRealName(realName, documentType, teamId))
                throw new RuntimeException("存在相同模板文件名称: " + realName);
            RemoteFileDto remoteFileDto = null;
            try {
                remoteFileDto = RemoteFileDto.builder().name(file.getName())
                    .file(file.getBytes())
                    .bucketName(OssBucketOneEnum
                        .PUBLIC_IMAGES.getCode())
                    .originalFilename(file.getOriginalFilename())
                    .moduleType(OssModuleType.Template).build();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            remoteFileDto.setContentType("file");
            RemoteFile remoteFile = remoteFileService.upload(remoteFileDto);
//            Storage storage = fileStorageUtils.create(user.getId().toString(), user.getUsername(), StorageFolderTypeEnum.TEAM_BUCKET.getCode(), file, FileEnums.TEAM_TEMPLATE, null);
            teamTemplateTree
                .setSuffix(extensionName)
                .setTeamId(teamId)
                .setType(documentType)
                .setRealName(realName)
                .setStorageId(remoteFile.getOssId().toString())
                .setStorageType(StorageTypeEnum.MINIO.getType())
                .setCreateTime(new Date());
            save(teamTemplateTree);
        }
    }

    @Override
    public void deleteAllByTeamId(String teamId) {
        Map<String, Object> columnMap = new HashMap<>();
        columnMap.put("team_id", teamId);
        removeByMap(columnMap);
    }


    /**
     * 公共删除方法
     */
    public void removeTemplate(TeamTemplateTreeDto teamTemplateTreeDto) {
        String storageId = teamTemplateTreeDto.getStorageId();
        if (storageId != null) {
            remoteFileService.deleteWithValidByIds(List.of(Long.valueOf(storageId)), false);
        }
        removeById(teamTemplateTreeDto.getId());
    }


    private boolean isExistRealName(String realName, String documentType, Long teamId) {
        TeamTemplateTreeQueryParam query = new TeamTemplateTreeQueryParam();
        query.setType(documentType);
        query.setTeamId(String.valueOf(teamId));
        QueryWrapper<TeamTemplateTree> predicate = QueryHelpMybatisPlus.getPredicate(query);
        predicate.eq("real_name", realName);
        return teamTemplateTreeMapper.selectOne(predicate) != null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteById(Long id) {
        Set<Long> set = new HashSet<>(1);
        set.add(id);
        return this.deleteByIds(set);
    }

    /*
    private void delCaches(Long id) {
        redisUtils.delByKey(CACHE_KEY + "::id:", id);
    }

    private void delCaches(Set<Long> ids) {
        for (Long id: ids) {
            delCaches(id);
        }
    }*/

    /*
    @Override
    public void download(List<TeamTemplateTreeDto> all, HttpServletResponse response) throws IOException {
      List<Map<String, Object>> list = new ArrayList<>();
      for (TeamTemplateTreeDto teamTemplateTree : all) {
        Map<String,Object> map = new LinkedHashMap<>();
              map.put("团队id", teamTemplateTree.getTeamId());
              map.put("后缀名", teamTemplateTree.getSuffix());
              map.put("名称", teamTemplateTree.getRealName());
              map.put("文件类型", teamTemplateTree.getFileType());
              map.put("储存表id", teamTemplateTree.getStorageId());
              map.put("储存服务器类型", teamTemplateTree.getStorageType());
              map.put("文件大小", teamTemplateTree.getSize());
              map.put("状态（0：未审批 1：已审批）", teamTemplateTree.getState());
              map.put("预览", teamTemplateTree.getPreview());
                map.put(" attention",  teamTemplateTree.getAttention());
              map.put("下载次数", teamTemplateTree.getDownload());
                map.put(" columnType",  teamTemplateTree.getColumnType());
              map.put("创建编号", teamTemplateTree.getCreateId());
              map.put("创建日期", teamTemplateTree.getCreateTime());
              map.put("更新编号", teamTemplateTree.getUpdateId());
              map.put("更新时间", teamTemplateTree.getUpdateTime());
              map.put("删除编号", teamTemplateTree.getDeleteId());
              map.put("删除时间", teamTemplateTree.getDeleteTime());
              map.put("版本", teamTemplateTree.getEditionName());
              map.put("描述", teamTemplateTree.getDescription());
        list.add(map);
      }
      FileUtil.downloadExcel(list, response);
    }*/
}
